home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_09_06 / 9n06078a < prev    next >
Text File  |  1990-02-27  |  7KB  |  197 lines

  1. /**************************************************************************
  2.  
  3.     getopt ()
  4.  
  5.  
  6.     Function GETOPT gets the next option letter from the command line.
  7.     GETOPT is an enhanced version of the C Library function, GETOPT(3).
  8.  
  9.  
  10.     Invocation:
  11.  
  12.         option = getopt (argc, argv, optstring) ;
  13.  
  14.     where
  15.  
  16.         <argc>
  17.             is the number of arguments in the argument value array.
  18.         <argv>
  19.             is the argument value array, i.e., an array of pointers to
  20.             the "words" extracted from the command line.
  21.         <optstring>
  22.             is the set of recognized options.  Each character in the
  23.             string is a legal option; any other character encountered
  24.             as an option in the command line is an illegal option and
  25.             an error message is displayed.  If a character is followed
  26.             by a colon in OPTSTRING, the option expects an argument.
  27.         <option>
  28.             returns the next option letter from the command line.  If
  29.             the option expects an argument, OPTARG is set to point to
  30.             the argument.  '?' is returned in the cases of an illegal
  31.             option letter or a missing option argument.  Constant NONOPT
  32.             is returned if a non-option argument is encountered or the
  33.             command line scan is completed (also see OPTARG below for
  34.             both cases).
  35.  
  36.  
  37.     Public Variables:
  38.  
  39.         OPTARG - returns the text of an option's argument or of a
  40.             non-option argument.  NULL is returned if an option
  41.             has no argument or if the command line scan is complete.
  42.             For illegal options or missing option arguments, OPTARG
  43.             returns a pointer to the trailing portion of the defective
  44.             ARGV.
  45.  
  46.         OPTERR - controls whether or not GETOPT prints out an
  47.             error message upon detecting an illegal option or
  48.             a missing option argument.  A non-zero value enables
  49.             error messages; zero disables them.
  50.  
  51.         OPTIND - is the index in ARGV of the command line argument
  52.             that GETOPT will examine next.  GETOPT recognizes changes
  53.             to this variable.  Arguments can be skipped by incrementing
  54.             OPTIND outside of GETOPT and the command line scan can be
  55.             restarted by resetting OPTIND to either 0 or 1.
  56.  
  57. **************************************************************************/
  58.  
  59.  
  60. #include  <stdio.h>                     /* Standard I/O definitions. */
  61. #define  USE_INDEX  0                   /* Set to 1 if your C Library uses
  62.                                            "index" instead of "strchr". */
  63. #if  USE_INDEX
  64. #    include  <strings.h>               /* C Library string functions. */
  65. #    define  strchr  index
  66. #else
  67. #    include  <string.h>                /* C Library string functions. */
  68. #endif
  69. #include  "getopt.h"                    /* GETOPT(3) definitions. */
  70.  
  71.                                         /* Public variables. */
  72. char  *optarg = NULL ;
  73. int  opterr = -1 ;
  74. int  optind = 0 ;
  75.                                         /* Private variables. */
  76. static  int  end_optind = 0 ;
  77. static  int  last_optind = 0 ;
  78. static  int  offset_in_group = 1 ;
  79.  
  80.  
  81.  
  82. int  getopt (argc, argv, optstring)
  83.  
  84.     int  argc ;
  85.     char  **argv ;
  86.     char  *optstring ;
  87.  
  88. {    /* Local variables. */
  89.  
  90.     char  *group, option, *s ;
  91.  
  92.  
  93.  
  94. /* Did the caller restart or advance the scan by modifying OPTIND? */
  95.  
  96.     if (optind <= 0) {
  97.         end_optind = 0 ;  last_optind = 0 ;  optind = 1 ;
  98.     }
  99.     if (optind != last_optind)  offset_in_group = 1 ;
  100.  
  101.  
  102. /**************************************************************************
  103.  
  104.     Scan the command line and return the next option or, if none, the
  105.     next non-option argument.  At the start of each loop iteration,
  106.     OPTIND is the index of the command line argument currently under
  107.     examination and OFFSET_IN_GROUP is the offset within the current
  108.     ARGV string of the next option (i.e., to be examined in this
  109.     iteration).
  110.  
  111. **************************************************************************/
  112.  
  113.  
  114.     for (option = ' ', optarg = NULL ;
  115.          optind < argc ;
  116.          optind++, offset_in_group = 1, option = ' ') {
  117.  
  118.         group = argv[optind] ;
  119.  
  120. /* Is this a non-option argument?  If it is and it's the same one
  121.    GETOPT returned on the last call, then loop and try the next
  122.    command line argument.  If it's a new, non-option argument,
  123.    then return the argument to the calling routine. */
  124.  
  125.         if ((group[0] != '-') ||
  126.             ((end_optind > 0) && (optind > end_optind))) {
  127.             if (optind == last_optind)  continue ;
  128.             optarg = group ;        /* Return NONOPT and argument. */
  129.             break ;
  130.         }
  131.  
  132. /* Are we at the end of the current options group?  If so, loop and
  133.    try the next command line argument. */
  134.  
  135.         if (offset_in_group >= strlen (group))  continue ;
  136.  
  137. /* If the current option is the end-of-options indicator, remember
  138.    its position and move on to the next command line argument. */
  139.  
  140.         option = group[offset_in_group++] ;
  141.         if (option == '-') {
  142.             end_optind = optind ;   /* Mark end-of-options position. */
  143.             continue ;
  144.         }
  145.  
  146. /* If the current option is an illegal option, print an error message
  147.    and return '?' to the calling routine. */
  148.  
  149.         s = strchr (optstring, option) ;
  150.         if (s == NULL) {
  151.             if (opterr)
  152.                 (void) fprintf (stderr, "%s: illegal option -- %c\n",
  153.                                 argv[0], option) ;
  154.             option = '?' ;  optarg = &group[offset_in_group-1] ;
  155.             break ;
  156.         }
  157.  
  158. /* Does the option expect an argument?  If yes, return the option and
  159.    its argument to the calling routine.  The option's argument may be
  160.    flush up against the option (i.e., the argument is the remainder of
  161.    the current ARGV) or it may be separated from the option by white
  162.    space (i.e., the argument is the whole of the next ARGV). */
  163.  
  164.         if (*++s == ':') {
  165.             if (offset_in_group < strlen (group)) {
  166.                 optarg = &group[offset_in_group] ;
  167.                 offset_in_group = strlen (group) ;
  168.             }
  169.             else {
  170.                 if ((++optind < argc) && (*argv[optind] != '-')) {
  171.                     optarg = argv[optind] ;
  172.                 } else {
  173.                     if (opterr)
  174.                         (void) fprintf (stderr,
  175.                               "%s: option requires an argument -- %c\n",
  176.                                         argv[0], option) ;
  177.                     option = '?' ;  optarg = &group[offset_in_group-1] ;
  178.                     offset_in_group = 1 ;
  179.                 }
  180.             }
  181.             break ;
  182.         }
  183.  
  184. /* It must be a single-letter option without an argument. */
  185.  
  186.         break ;
  187.  
  188.     }
  189.  
  190.  
  191. /* Return the option and (optionally) its argument. */
  192.  
  193.     last_optind = optind ;
  194.     return ((option == ' ') ? NONOPT : (int) option) ;
  195.  
  196. }
  197.